/**
 * @file pedometer.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_PEDOMETER!= 0

#include <stdio.h>

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static lv_obj_t * digital_content_create(lv_obj_t * par, int16_t level, uint8_t first_time);
static int16_t pedometer_set_value(lv_obj_t * pedometer);
static lv_obj_t * pedometer_get_pedoobj(void);

/**********************
 *  STATIC VARIABLES
 **********************/
static uint16_t pedometer_steps = 1000;  //1000 is test value
static uint16_t pedometer_goalsteps = 10000;

/**********************
 *      MACROS
 **********************/
#define PEDOMETER_DEF_ANGLE              5000
#define PEDOMETER_CIRCLE_START           340
#define PEDOMETER_CIRCLE_END             3300
#define PEDOMETER_CIRCLE_R               100
#define PEDOMETER_CIRCLE_R_OFFSET        1
/**********************
 *   GLOBAL FUNCTIONS
***********************/
lv_obj_t * pedometer_create(lv_obj_t * tileview, uint16_t id)
{
    lv_obj_t * tab;
    if(id == 0xFF) {
        tab = tileview;
    } else {
        tab = launcher_tileview_add_tile(tileview, id);
        LV_ASSERT_MEM(tab);
        if(tab == NULL) return NULL;
    }

    lv_obj_t * img_color_circle = lv_img_create(tab, NULL);
    LV_ASSERT_MEM(img_color_circle);
    if(img_color_circle == NULL) return NULL;
    lv_img_set_src(img_color_circle, ICON_COLOR_CIRCLE);
    lv_obj_add_style(img_color_circle, LV_IMG_PART_MAIN, &lv_watch_image);
    lv_obj_align(img_color_circle, tab, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * pedometer = lv_img_create(img_color_circle, NULL);
    lv_img_set_src(pedometer, ICON_STEP_DOT);
    lv_obj_set_pos(pedometer, LV_HOR_RES / 2 - lv_obj_get_width(pedometer) / 2,
                   LV_VER_RES / 2 + 100 - lv_obj_get_height(pedometer) / 2);
    lv_img_set_pivot(pedometer, lv_obj_get_width(pedometer) / 2,
                     - (PEDOMETER_CIRCLE_R - lv_obj_get_width(pedometer) / 2 + PEDOMETER_CIRCLE_R_OFFSET));

    lv_obj_t * content = lv_watch_cont_create(img_color_circle, LV_LAYOUT_COLUMN_MID, &lv_style_transp_fit, lv_obj_get_width(img_color_circle));

    lv_obj_t * label = lv_label_create(content, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font30);
    lv_label_set_text_id(label, WATCH_TEXT_ID_TODAY);
    lv_obj_set_click(label, false);

#if USE_LV_WATCH_BODYINFO!= 0
    nv_watch_pedometer_setting_t pedo;
    memset(&pedo, 0, sizeof(nv_watch_pedometer_setting_t));
    bodyinfo_init(&pedo);
    pedometer_set_goalsteps(pedo.goal);
#endif

    pedometer_set_value(pedometer);
    lv_obj_t * digital_content = digital_content_create(content, pedometer_steps, 1);

    label = lv_label_create(content, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font30);
    lv_label_set_text_id(label, WATCH_TEXT_ID_STEPS);
    lv_obj_set_click(label, false);

    lv_obj_t * img = lv_img_create(content, NULL);
    LV_ASSERT_MEM(img);
    if(img == NULL) return NULL;
    lv_img_set_src(img, ICON_FLAG);

    label = lv_label_create(content, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font30);
    char str[10] = "";
    snprintf(str, sizeof(str), "%d", pedometer_goalsteps);
    lv_label_set_text(label, str);
    lv_obj_set_click(label, false);

    lv_obj_align(content, NULL, LV_ALIGN_CENTER, 0, 15);
#if USE_LV_WATCH_LAUNCHER != 0
    lv_drop_pull_obj_ext_t * ext = launcher_get_dp_ext();
#elif USE_LV_WATCH_LAUNCHER2 != 0
    lv_pedometer_ext_t * ext = lv_obj_allocate_ext_attr(tab, sizeof(lv_pedometer_ext_t));
#endif
    if(ext != NULL) {
        ext->pedometer_dot = pedometer;
        ext->pedometer_cont = digital_content;
        ext->pedometer_goal = label;
    }

    lv_tileview_add_element(tileview, pedometer);
    lv_tileview_add_element(tileview, img_color_circle);
    lv_tileview_add_element(tileview, content);
    lv_obj_set_click(img_color_circle, false);
    lv_obj_set_click(content, false);
    lv_obj_set_click(pedometer, false);

    return tab;
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
void pedometer_set_steps(uint16_t steps)
{
    pedometer_steps = steps;
}

uint16_t pedometer_get_steps(void)
{
    return pedometer_steps;
}

void pedometer_set_goalsteps(uint16_t goal)
{
    pedometer_goalsteps = goal;
}

uint16_t pedometer_get_goalsteps(void)
{
    return pedometer_goalsteps;
}

lv_pedometer_ext_t * pedometer_get_ext(void)
{
    lv_pedometer_ext_t * ext = NULL;
    lv_obj_t * tab = NULL;
    lv_obj_t * obj = lv_watch_get_activity_obj(ACT_ID_PEDOMETER);
    if(obj) {
        lv_obj_t * tileview = lv_obj_get_child_back(obj, NULL);
        lv_obj_t * scrl = lv_page_get_scrl(tileview);
        tab = lv_obj_get_child(scrl, lv_obj_get_child(scrl, NULL));
    }
    if(tab)
        ext = lv_obj_get_ext_attr(tab);
    return ext;
}

void pedometer_update_goal(uint16_t goal)
{
    pedometer_set_goalsteps(goal);

    lv_obj_t * pedometer = pedometer_get_pedoobj();
    pedometer_set_value(pedometer);

    lv_obj_t * label = NULL;
#if USE_LV_WATCH_LAUNCHER != 0
    lv_drop_pull_obj_ext_t * ext = launcher_get_dp_ext();
#elif USE_LV_WATCH_LAUNCHER2 != 0
    if(lv_watch_get_activity_obj(ACT_ID_PEDOMETER) == NULL) return;
    lv_pedometer_ext_t * ext = pedometer_get_ext();
#endif
    if(ext == NULL) return;
    label = ext->pedometer_goal;
    char str[10] = "";
    snprintf(str, sizeof(str), "%d", pedometer_goalsteps);
    lv_label_set_text(label, str);
}

void pedometer_update_steps(uint16_t steps)
{
    pedometer_set_steps(steps);
#if USE_LV_WATCH_LAUNCHER != 0
    lv_drop_pull_obj_ext_t * ext = launcher_get_dp_ext();
#elif USE_LV_WATCH_LAUNCHER2 != 0
    if(lv_watch_get_activity_obj(ACT_ID_PEDOMETER) == NULL) return;
    lv_pedometer_ext_t * ext = pedometer_get_ext();
#endif
    if(ext == NULL) return;

    lv_obj_t * pedometer = NULL;
    lv_obj_t * pedometer_cont = NULL;

    pedometer = ext->pedometer_dot;
    pedometer_cont = ext->pedometer_cont;
    pedometer_set_value(pedometer);

    lv_obj_clean(pedometer_cont);
    digital_content_create(pedometer_cont, pedometer_steps, 0);
}

static lv_obj_t * pedometer_get_pedoobj(void)
{
#if USE_LV_WATCH_LAUNCHER != 0
    lv_drop_pull_obj_ext_t * ext = launcher_get_dp_ext();
#elif USE_LV_WATCH_LAUNCHER2 != 0
    if(lv_watch_get_activity_obj(ACT_ID_PEDOMETER) == NULL) return NULL;
    lv_pedometer_ext_t * ext = pedometer_get_ext();
#endif
    return ext->pedometer_dot;
}

static int16_t pedometer_set_value(lv_obj_t * pedometer)
{
    float delta = (float)pedometer_steps / pedometer_goalsteps;
    int16_t val = delta * (PEDOMETER_CIRCLE_END - PEDOMETER_CIRCLE_START) + PEDOMETER_CIRCLE_START;
    if(val < PEDOMETER_CIRCLE_START) val = PEDOMETER_CIRCLE_START;
    if(val > PEDOMETER_CIRCLE_END) val = PEDOMETER_CIRCLE_END;
    lv_img_set_angle(pedometer, val);
    return val;
}

static lv_obj_t * digital_content_create(lv_obj_t * par, int16_t level, uint8_t first_time)
{
    lv_obj_t * par_obj = NULL;
    if(first_time) {
        lv_obj_t * content = lv_watch_cont_create(par, LV_LAYOUT_ROW_MID, &lv_style_transp_fit, lv_obj_get_width(par));
        lv_cont_set_fit2(content, LV_FIT_TIGHT, LV_FIT_TIGHT);
        lv_obj_align(content, par, LV_ALIGN_CENTER, 0, 0);
        par_obj = content;
    } else {
        par_obj = par;
    }
    lv_cont_set_layout(par_obj, LV_LAYOUT_OFF);

    char str[10] = "";
    snprintf(str, sizeof(str), "%d", level);

    const void * digitalSrcList[] = {
        ICON_PEDOMETER_DIGITAL_0,
        ICON_PEDOMETER_DIGITAL_1,
        ICON_PEDOMETER_DIGITAL_2,
        ICON_PEDOMETER_DIGITAL_3,
        ICON_PEDOMETER_DIGITAL_4,
        ICON_PEDOMETER_DIGITAL_5,
        ICON_PEDOMETER_DIGITAL_6,
        ICON_PEDOMETER_DIGITAL_7,
        ICON_PEDOMETER_DIGITAL_8,
        ICON_PEDOMETER_DIGITAL_9,
    };

    for(int8_t i = 0; i < strlen(str); i++) {
        lv_obj_t * img = lv_img_create(par_obj, NULL);
        LV_ASSERT_MEM(img);
        if(img == NULL) return NULL;
        lv_img_set_src(img, digitalSrcList[str[i] - '0']);
        lv_obj_align(img, NULL, LV_ALIGN_IN_TOP_LEFT, i * (lv_obj_get_width(img) + 5), 0);
    }
    return par_obj;
}

#endif /*USE_LV_WATCH_PEDOMETER*/
